/***************************************************************************
 * Open Object Oriented ANSI C                                             *
 ***************************************************************************
 * Code given under the terms of GNU General Public Licence (GPLv3)        *
 * and without any waranties of any kind including but not limitative to   *
 * waranties on merchandability or any particular applications fitness.    *
 * For more information on GNU/GPL go on :                                 *
 * "http://www.gnu.org/copyleft/gpl.html"                                  *
 *                                                                         *
 * You are allowed to use it for any purposes in the terms of GNU/GPLv3    *
 * (or more).                                                              *
 * This text MUST stay in state on copyed sources (or sources using it)    *
 * and must not be altered.                                                *
 * You are allowed to add your name at the end of the Copylefs list.       *
 ***************************************************************************
 * Copylefts List :                                                        *
 ***************************************************************************
 * 2010-03-20 Patrick PIGNOL <pignol_patrick@hotmail.com> (Original)       *
 * (Type your name here if needed)                                         *
 ***************************************************************************/
#ifndef EXCEPTIONMANAGER_H_INCLUDED
#define EXCEPTIONMANAGER_H_INCLUDED

#define EXCEPTIONMANAGER_TYPEID 3

typedef struct ExceptionManagerVirtualTable ExceptionManagerVirtualTable;
typedef struct ExceptionManager ExceptionManager;

#include "Bool.h"
#include "Exception.h"
#include "Stack.h"

/*sealed (or finalized) class*/

struct ExceptionManagerVirtualTable
{
    unsigned long int TypeID;
    ClassInterface* Interface;
    ClassVirtualTable* AncestorTable;
    unsigned long int ReferenceCount;
    ExceptionManager* (*new)(unsigned long int pArgsCount, va_list* pParameters);
    ExceptionManagerVirtualTable* (*Initialize)(ExceptionManager* this, unsigned long int pArgsCount, va_list* pParameters);
    void (*Garbage)(ExceptionManager* this);
    unsigned long int (*TypeOf)(ExceptionManager* this);
    bool (*IsSameTypeThanTypeID)(ExceptionManager* this, unsigned long int pTypeID);
    bool (*IsKindOfTypeID)(ExceptionManager* this, unsigned long int pTypeID);
    bool (*IsSameTypeThan)(ExceptionManager* this, Class* pSource);
    bool (*IsKindOf)(ExceptionManager* this, Class* pSource);
};

struct ExceptionManager
{
    ExceptionManagerVirtualTable* VirtualTable;
    void (*Constructor)(ExceptionManager* this, unsigned long int pArgsCount, va_list* pParameters);
    void (*Destructor)(ExceptionManager* this);
    ExceptionManager* (*Clone)(ExceptionManager* this);
    bool aConstructed;
    ExceptionManager* (*GetInstance)();
    Stack* aExceptionStateRecovers;
    void (*TryInitialize)();
    void (*catch)(const unsigned long int, Class*, void (*)(Class*, Exception*, unsigned long int pArgsCount, va_list*));
    void (*try)(Class* pTargetClass, void (*pTryedMethod)(Class*, unsigned long int, va_list*), unsigned long int pArgsCount, ...);
    void (*throw)(Exception* pException);
};

ExceptionManager* ExceptionManagerNew(unsigned long pArgsCount, va_list* pParameters);
ExceptionManagerVirtualTable* ExceptionManagerInitialize(ExceptionManager* this, unsigned long pArgsCount, va_list* pParameters);
void ExceptionManagerConstructor(ExceptionManager* this, unsigned long int pArgsCount, va_list* pParameters);
void ExceptionManagerDestructor(ExceptionManager* this);
ExceptionManager* ExceptionManagerClone(ExceptionManager* this);
ExceptionManager* ExceptionManagerGetInstance();
void ExceptionManagerTryInitialize();
void ExceptionManagerTry(Class* pTargetClass, void (*pTryedMethod)(Class*, unsigned long int, va_list*), unsigned long int pArgsCount, ...); /* Exception type to catch, class asking catching ,ExceptionHandlerMethod(targetClass, Throwed Exception); */
void ExceptionManagerCatch(const unsigned long int, Class*, void (*)(Class*, Exception*, unsigned long int pArgsCount, va_list*));
void ExceptionManagerThrow(Exception* pException);
#endif /* EXCEPTIONMANAGER_H_INCLUDED*/
